package com.kxmall.huishou.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.binarywang.wx.miniapp.bean.WxMaTemplateData;
import cn.binarywang.wx.miniapp.bean.WxMaUniformMessage;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.PhoneUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kxmall.categorize.domain.vo.HsWasteCategorizeVo;
import com.kxmall.categorize.service.IHsWasteCategorizeService;
import com.kxmall.common.core.domain.PageQuery;
import com.kxmall.common.core.page.TableDataInfo;
import com.kxmall.common.exception.ServiceException;
import com.kxmall.common.utils.StringUtils;
import com.kxmall.huishou.domain.HsAppointmentOrder;
import com.kxmall.huishou.domain.bo.HsAppointmentOrderBo;
import com.kxmall.huishou.domain.bo.HsUserWasteBo;
import com.kxmall.huishou.domain.vo.HsAppointmentOrderVo;
import com.kxmall.huishou.mapper.HsAppointmentOrderMapper;
import com.kxmall.huishou.service.IHsAppointmentOrderService;
import com.kxmall.huishou.service.IHsUserWasteService;
import com.kxmall.rider.domain.KxRider;
import com.kxmall.rider.domain.vo.HsRiderStatisticsVo;
import com.kxmall.rider.mapper.KxRiderMapper;
import com.kxmall.system.domain.SysConfig;
import com.kxmall.system.domain.SysNotice;
import com.kxmall.system.mapper.SysConfigMapper;
import com.kxmall.system.mapper.SysNoticeMapper;
import com.kxmall.wechat.WxMaConfiguration;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 回收预约订单信息Service业务层处理
 *
 * @author kxmall
 * @date 2023-11-23
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class HsAppointmentOrderServiceImpl implements IHsAppointmentOrderService {

    private final HsAppointmentOrderMapper baseMapper;
    private final SysNoticeMapper sysNoticeMapper;
    private final IHsWasteCategorizeService iHsWasteCategorizeService;
    private final IHsUserWasteService iHsUserWasteService;
    private final KxRiderMapper kxRiderMapper;
    private final SysConfigMapper sysConfigMapper;

    /**
     * 查询回收预约订单信息
     */
    @Override
    public HsAppointmentOrderVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    public TableDataInfo<HsAppointmentOrderVo> queryPageLists(HsAppointmentOrderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<HsAppointmentOrder> lqw = buildQueryWrapper(bo);
//        Page<HsAppointmentOrderVo> result = baseMapper.selectVoPageNew(pageQuery.build(), bo);
//        Page<HsAppointmentOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        IPage<HsAppointmentOrder> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        Page<HsAppointmentOrderVo> result = null;
        if (bo.getStatus() != null && bo.getStatus() == 0) {
            result = baseMapper.selectVoPageForAddress(page, bo);
        } else {
            result = baseMapper.selectVoPageForTime(page, bo);
        }

        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<HsAppointmentOrderVo> queryPageListByStatus(HsAppointmentOrderBo bo, PageQuery pageQuery) {

        LambdaQueryWrapper<HsAppointmentOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, HsAppointmentOrder::getUserId, bo.getUserId());
        lqw.eq(bo.getRiderId() != null, HsAppointmentOrder::getRiderId, bo.getRiderId());
        if (bo.getStatus() != null) {
            if (bo.getStatus() == 2l || bo.getStatus() == 4l) {
                List<Long> statusList = new ArrayList<>();
                statusList.add(2l);
                statusList.add(4l);
                lqw.in(HsAppointmentOrder::getStatus, statusList);
            } else if (bo.getStatus() == 5l || bo.getStatus() == 6l) {
                List<Long> statusList = new ArrayList<>();
                statusList.add(5l);
                statusList.add(6l);
                lqw.in(HsAppointmentOrder::getStatus, statusList);
            } else if (bo.getStatus() == 7 || bo.getStatus() == 8 || bo.getStatus() == 9) {
                List<Long> statusList = new ArrayList<>();
                statusList.add(7l);
                statusList.add(8l);
                statusList.add(9l);
                lqw.in(HsAppointmentOrder::getStatus, statusList);
            } else {
                lqw.eq(HsAppointmentOrder::getStatus, bo.getStatus());
            }
        }

        Page<HsAppointmentOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询回收预约订单信息列表
     */
    @Override
    public TableDataInfo<HsAppointmentOrderVo> queryPageList(HsAppointmentOrderBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<HsAppointmentOrder> lqw = buildQueryWrapper(bo);
        Page<HsAppointmentOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询回收预约订单信息列表
     */
    @Override
    public List<HsAppointmentOrderVo> queryList(HsAppointmentOrderBo bo) {
        LambdaQueryWrapper<HsAppointmentOrder> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<HsAppointmentOrderVo> queryListByOverTime() {
        LambdaQueryWrapper<HsAppointmentOrder> lqw = Wrappers.lambdaQuery();
        lqw.lt(HsAppointmentOrder::getEndTime, new Date());
        lqw.eq(HsAppointmentOrder::getStatus, 0);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<HsAppointmentOrder> buildQueryWrapper(HsAppointmentOrderBo bo) {
//        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<HsAppointmentOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getOrderNo()), HsAppointmentOrder::getOrderNo, bo.getOrderNo());
        lqw.eq(bo.getUserId() != null, HsAppointmentOrder::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getContactor()), HsAppointmentOrder::getContactor, bo.getContactor());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), HsAppointmentOrder::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getProvince()), HsAppointmentOrder::getProvince, bo.getProvince());
        lqw.eq(StringUtils.isNotBlank(bo.getCity()), HsAppointmentOrder::getCity, bo.getCity());
        lqw.eq(StringUtils.isNotBlank(bo.getCounty()), HsAppointmentOrder::getCounty, bo.getCounty());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), HsAppointmentOrder::getAddress, bo.getAddress());
//        lqw.eq(bo.getLongitude() != null, HsAppointmentOrder::getLongitude, bo.getLongitude());
//        lqw.eq(bo.getLatitude() != null, HsAppointmentOrder::getLatitude, bo.getLatitude());
        lqw.eq(bo.getStartTime() != null, HsAppointmentOrder::getStartTime, bo.getStartTime());
        lqw.eq(bo.getEndTime() != null, HsAppointmentOrder::getEndTime, bo.getEndTime());
        lqw.eq(bo.getRiderId() != null, HsAppointmentOrder::getRiderId, bo.getRiderId());
        lqw.eq(bo.getTakingTime() != null, HsAppointmentOrder::getTakingTime, bo.getTakingTime());
        lqw.eq(bo.getArriveTime() != null, HsAppointmentOrder::getArriveTime, bo.getArriveTime());
        lqw.eq(bo.getCompleteTime() != null, HsAppointmentOrder::getCompleteTime, bo.getCompleteTime());
        lqw.orderByDesc(HsAppointmentOrder::getCreateTime);
        if (bo.getStatus() != null) {
            if (bo.getStatus() == 5l || bo.getStatus() == 6l) {
                List<Long> statusList = new ArrayList<>();
                statusList.add(5l);
                statusList.add(6l);
                lqw.in(HsAppointmentOrder::getStatus, statusList);
            } else if (bo.getStatus() == 7 || bo.getStatus() == 8 || bo.getStatus() == 9) {
                List<Long> statusList = new ArrayList<>();
                statusList.add(7l);
                statusList.add(8l);
                statusList.add(9l);
                lqw.in(HsAppointmentOrder::getStatus, statusList);
            } else {
                lqw.eq(HsAppointmentOrder::getStatus, bo.getStatus());
            }
        }

        return lqw;
    }

    /**
     * 新增回收预约订单信息
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @Override
    public Boolean insertByBo(HsAppointmentOrderBo bo) {
        HsAppointmentOrder appointmentOrder = BeanUtil.toBean(bo, HsAppointmentOrder.class);
//        validEntityBeforeSave(appointmentOrder);
        boolean flag = baseMapper.insert(appointmentOrder) > 0;
        if (flag) {
            bo.setId(appointmentOrder.getId());
        } else {
            return false;
        }

        //保存预约废品
        if (bo.getHsUserWasteBoList() != null) {

            BigDecimal exceptWeight = BigDecimal.ZERO;
            BigDecimal exceptAmount = BigDecimal.ZERO;

            for (HsUserWasteBo hsUserWasteBo : bo.getHsUserWasteBoList()) {
                hsUserWasteBo.setOrderType(0l);
                hsUserWasteBo.setOrderId(bo.getId());
                HsWasteCategorizeVo hsWasteCategorizeVo = iHsWasteCategorizeService.queryById(hsUserWasteBo.getCategorizeId());
                if (hsWasteCategorizeVo == null) {
                    throw new RuntimeException("HsWasteCategorizeVo is not exit");
                }
                hsUserWasteBo.setCategorizeName(hsWasteCategorizeVo.getName());
                hsUserWasteBo.setPrice(hsWasteCategorizeVo.getPrice());
                exceptWeight = exceptWeight.add(hsUserWasteBo.getWeight());
                exceptAmount = exceptAmount.add(hsUserWasteBo.getAmount());
            }

            if (appointmentOrder.getExpectWeightTal().compareTo(exceptWeight) != 0 || appointmentOrder.getExpectAmountTal().compareTo(exceptAmount) != 0) {
                appointmentOrder.setExpectAmountTal(exceptAmount);
                appointmentOrder.setExpectWeightTal(exceptWeight);
                baseMapper.updateById(appointmentOrder);
            }

            iHsUserWasteService.insertOrUpdateByBoList(bo.getHsUserWasteBoList());

        }

        //发送消息给回收员
        try {
            SysNotice sysNotice = new SysNotice();
            sysNotice.setNoticeTitle(bo.getAddress() + "有新的预约回收订单等待接单");
            sysNotice.setNoticeType("1");
            sysNotice.setNoticeContent("有新的预约回收订单等待接单，回收地址：" + bo.getPhone() + bo.getCity() + bo.getAddress() + ",预约时间：" + DateUtil.format(bo.getStartTime(), "yyyy-MM-dd HH:mm:ss") + "-" + DateUtil.format(bo.getEndTime(), "yyyy-MM-dd HH:mm:ss"));
            sysNotice.setStatus("0");
            sysNotice.setOrderId(bo.getId());
            sysNotice.setUserType(2);
            sysNoticeMapper.insert(sysNotice);
            // todo 推送模板消息给回收员
            ThreadUtil.execAsync(()->{
                sendTemplateMsg(bo.getAddress(),bo.getOrderNo(),bo.getPhone());
            });

        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }

        return flag;
    }

    private void sendTemplateMsg(String orderAddress,String orderNo,String phone) {
        LambdaQueryWrapper<KxRider> riderWrapper = new LambdaQueryWrapper<>();
        riderWrapper.isNotNull(KxRider::getOpenId);
        List<KxRider> kxRiders = kxRiderMapper.selectList();
        if (CollUtil.isEmpty(kxRiders)) {
            log.info("当前没有回收员或者是当前回收员没有通过微信登录");
            return;
        }
        LambdaQueryWrapper<SysConfig> sysConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysConfigLambdaQueryWrapper.in(SysConfig::getConfigKey,"rider_mini_grab_order_temp_id","rider_mini_grab_order_temp_id_url","rider_mini_grab_order_temp_id_pages");
        List<SysConfig> sysConfigList = sysConfigMapper.selectList(sysConfigLambdaQueryWrapper);
        if (CollUtil.isEmpty(sysConfigList) || sysConfigList.size() != 3) {
            log.info("当前没有回收员小程序的模板消息id");
            return;
        }

        Map<String, String> sysConfigMap = sysConfigList.stream().collect(Collectors.toMap(SysConfig::getConfigKey,SysConfig::getConfigValue));

        WxMaSubscribeMessage subscribeMessage = null;

        List<WxMaSubscribeMessage.MsgData> data = new ArrayList<>();
        WxMaSubscribeMessage.MsgData  wxMaTemplateData = new WxMaSubscribeMessage.MsgData();
        wxMaTemplateData.setName("character_string1");
        wxMaTemplateData.setValue(orderNo);
        data.add(wxMaTemplateData);
        wxMaTemplateData = new WxMaSubscribeMessage.MsgData();
        wxMaTemplateData.setName("thing2");
        wxMaTemplateData.setValue(orderAddress);
        data.add(wxMaTemplateData);
        wxMaTemplateData = new WxMaSubscribeMessage.MsgData();
        wxMaTemplateData.setName("time3");
        wxMaTemplateData.setValue(DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
        data.add(wxMaTemplateData);
        wxMaTemplateData = new WxMaSubscribeMessage.MsgData();
        wxMaTemplateData.setName("thing4");
        wxMaTemplateData.setValue("无备注");
        data.add(wxMaTemplateData);
        wxMaTemplateData = new WxMaSubscribeMessage.MsgData();
        wxMaTemplateData.setName("phone_number5");
        wxMaTemplateData.setValue(PhoneUtil.hideBetween(phone).toString());
        data.add(wxMaTemplateData);

        for (KxRider kxRider : kxRiders) {

            String openId = kxRider.getOpenId();
            if (StrUtil.isBlank(openId)){
                continue;
            }
            subscribeMessage = new WxMaSubscribeMessage();
            subscribeMessage.setToUser(openId);
            subscribeMessage.setTemplateId(sysConfigMap.get("rider_mini_grab_order_temp_id"));
            subscribeMessage.setPage(sysConfigMap.get("rider_mini_grab_order_temp_id_pages"));

            subscribeMessage.setData(data);
            WxMaService riderWxMaService = WxMaConfiguration.getRiderWxMaService();
            try {
                // 如果过期了，就刷新token
                String accessToken = riderWxMaService.getAccessToken(true);
                riderWxMaService.getMsgService().sendSubscribeMsg(subscribeMessage);
                log.info("推送模板消息成功");
            } catch (WxErrorException e) {
                log.error("推送模板消息失败：{}", e.getMessage(), e);
                throw new RuntimeException(e);
            }
        }

    }

    /**
     * 修改回收预约订单信息
     */
    @Override
    public Boolean updateByBo(HsAppointmentOrderBo bo) {
        HsAppointmentOrder update = BeanUtil.toBean(bo, HsAppointmentOrder.class);
        validEntityBeforeSave(update);

        HsAppointmentOrderVo hsAppointmentOrderVo = baseMapper.selectVoById(bo.getId());
        if (hsAppointmentOrderVo == null || hsAppointmentOrderVo.getUserId().longValue() != bo.getUserId().longValue() || hsAppointmentOrderVo.getStatus() != 0) {
            return false;
        }

        if (bo.getHsUserWasteBoList() != null) {
            for (HsUserWasteBo hsUserWasteBo : bo.getHsUserWasteBoList()) {
                hsUserWasteBo.setOrderType(0l);
                hsUserWasteBo.setOrderId(bo.getId());
                HsWasteCategorizeVo hsWasteCategorizeVo = iHsWasteCategorizeService.queryById(hsUserWasteBo.getCategorizeId());
                if (hsWasteCategorizeVo == null) {
                    continue;
                }
                hsUserWasteBo.setCategorizeName(hsWasteCategorizeVo.getName());
                hsUserWasteBo.setPrice(hsWasteCategorizeVo.getPrice());
            }
        }

        iHsUserWasteService.insertOrUpdateByBoList(bo.getHsUserWasteBoList());
        update.setRiderId(hsAppointmentOrderVo.getRiderId());
        update.setArriveTime(hsAppointmentOrderVo.getArriveTime());
        update.setCompleteTime(hsAppointmentOrderVo.getCompleteTime());

        return baseMapper.updateById(update) > 0;
    }


    /**
     * 修改回收预约订单信息
     */
    @Override
    public Boolean updateById(HsAppointmentOrderBo bo) {
        HsAppointmentOrder update = BeanUtil.toBean(bo, HsAppointmentOrder.class);

        return baseMapper.updateById(update) > 0;
    }


    /**
     * 取消回收预约订单信息
     */
    @Override
    public Boolean cancelById(Long id) {
        HsAppointmentOrder appointmentOrder = new HsAppointmentOrder();
        appointmentOrder.setId(id);
        appointmentOrder.setStatus(1l);

        int num = baseMapper.update(appointmentOrder, new QueryWrapper<HsAppointmentOrder>().eq("id", id));
        return num > 0;
    }


    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(HsAppointmentOrder entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除回收预约订单信息
     */
    @Override
    @Transactional
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
            for (Long id : ids) {
                // 在这里你可以对每个 id 进行需要的操作
                HsAppointmentOrderVo hsAppointmentOrderVo = baseMapper.selectVoByIds(id);
                if (hsAppointmentOrderVo.getStatus() == 0
                        || hsAppointmentOrderVo.getStatus() == 2
                        || hsAppointmentOrderVo.getStatus() == 3
                        || hsAppointmentOrderVo.getStatus() == 4) {
                    throw new ServiceException("订单处于流程状态,不可删除");
                }
                iHsUserWasteService.deletaByOrderId(hsAppointmentOrderVo.getId());
            }

        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }


    @Override
    public Boolean dealOrderByRider(HsAppointmentOrder appointmentOrder) {
        if (appointmentOrder == null || appointmentOrder.getId() == null) {
            return false;
        }
        int num = baseMapper.update(appointmentOrder, new QueryWrapper<HsAppointmentOrder>().eq("id", appointmentOrder.getId()));
        return num > 0;
    }

    @Override
    public HsRiderStatisticsVo riderStatistics() {
        HsRiderStatisticsVo hsRiderStatisticsVo = new HsRiderStatisticsVo();

//        baseMapper.

        return hsRiderStatisticsVo;
    }


    public Long countMinuteByRiderId(Long riderId) {
        return baseMapper.countMinuteByRiderId(riderId);
    }

    public Long countOrderByRiderId(Long riderId, List<Long> statusList, Date startTime, Date endTime) {
        if (statusList == null || statusList.size() <= 0) {
            return baseMapper.countOrderByRiderIdAndStatus(riderId, null, startTime, endTime);
        } else {
            String statusStr = "";
            for (int i = 0; i < statusList.size(); i++) {
                Long status = statusList.get(i);

                if (i < (statusList.size() - 1)) {
                    statusStr = statusStr + status + ",";
                } else {
                    statusStr = statusStr + status;
                }
            }
            return baseMapper.countOrderByRiderIdAndStatus(riderId, statusStr, startTime, endTime);
        }

//        return baseMapper.countOrderByRiderIdAndStatus(riderId, statusList, startTime, endTime);

    }
}
